package com.ease.map.control {
    import com.ease.map.Map;
    import com.ease.map.common.util.ResourceUtil;
    import com.ease.map.constant.StringConstants;
    import com.ease.map.events.LayerEvent;
    import com.ease.map.events.MapEvent;
    import com.ease.map.geometry.basetype.Pixel;
    import com.ease.map.geometry.basetype.Unit;

    import flash.events.Event;
    import flash.text.TextField;
    import flash.text.TextFormat;
    import com.ease.map.control.Control;

    /**
     * The scaleLine
     * Calcul and display an approximate scale of the current baselayer.
     */
    [ResourceBundle("MapCore")]
    public class ScaleLine extends Control {

        /**
         * Maximum width of the scale line in pixels.  Default is 100.
         */
        private var _scaleMaxWidth:Number = 120;

        /**
         * Units for zoomed out on top bar.  Default is km.
         */
        private var _topOutUnits:String = ResourceUtil.getString(StringConstants.MAP_UNIT_KILOMETER);

        /**
         * Units for zoomed in on top bar.  Default is m.
         */
        private var _topInUnits:String = ResourceUtil.getString(StringConstants.MAP_UNIT_METER);

        /**
         * Units for zoomed out on bottom bar.  Default is mi.
         */
        private var _bottomOutUnits:String = ResourceUtil.getString(StringConstants.MAP_UNIT_MILE);

        /**
         * Units for zoomed in on bottom bar.  Default is ft.
         */
        private var _bottomInUnits:String = ResourceUtil.getString(StringConstants.MAP_UNIT_FOOT);

        /**
         * Label wich display the distance in miles, or feet represented by the scaleLine.
         */
        private var _labelMiles:TextField = null;

        /**
         * Label wich display the distance in kilometers, or meters represented by the scaleLine.
         */
        private var _labelKm:TextField = null;

        private var _colorText:int = 0x000000;

        private var _colorScaleLine:int = 0x000000;

        /**
         * Size (or lenght) in pixel of the scaleLine, just before drawing (and after calculating size)
         */
        private var _topPx:Number;

        /**
         * Constructor
         *
         */
        public function ScaleLine(position:Pixel = null) {
            super(position);
        }

        /**
         * Get the existing map and add event listener on event Zoom end and baseLayer change.
         *
         * @param value
         */
        override public function set map(value:Map):void {
            if (value != null) {
                this._map = value;
                this.map.addEventListener(MapEvent.MOVE_END, updateScaleLineOnMove);
            }
        }

        override public function draw():void {
            super.draw();
            this.updateScale();
        }

        /**
         * Redraw the scaleline with new parameters.
         *
         * @param event the event can be a MapEvent.MOVE_END.
         */
        public function updateScaleLineOnMove(e:MapEvent):void {
            if (e.zoomChanged)
                this.draw()
        }

        public function updateScaleLineOnBaseLayerChanged(e:LayerEvent):void {
            this.draw()
        }



        /**
         * Given a number, round it down to the nearest 1,2,5 times a power of 10.
         * That seems a fairly useful set of number groups to use.
         *
         * @param maxLen the number we're rounding down from
         *
         * @return the rounded number (less than or equal to maxLen)
         */
        private function getBarLen(maxLen:Number):Number {
            // nearest power of 10 lower than maxLen
            var digits:Number = int(Math.log(maxLen) / Math.log(10));
            var pow10:Number = Math.pow(10, digits);

            // ok, find first character
            var firstChar:Number = int(maxLen / pow10);

            // right, put it into the correct bracket
            var barLen:Number;
            if (firstChar > 5) {
                barLen = 5;
            }
            else if (firstChar > 2) {
                barLen = 2;
            }
            else {
                barLen = 1;
            }

            // scale it up the correct power of 10
            return barLen * pow10;
        }

        /**
         * Update the size of the bars, and the labels which contains.
         */
        private function updateScale():void {
            // Get the resolution of the map
            var mapResolution:Number = this.map.resolution;

            // Map has no resolution, return.
            if (!mapResolution) {
                return;
            }

            // get the current units of the map
            /* var currentBaseLayerUnits:String = this.map.units; */
            var currentBaseLayerUnits:String = this.map.projection.projParams.units;

            // convert the scaleMaxWidth to map units
            // The result is the max distance IN MAP UNIT, represent in the scaleline
            var maxSizeData:Number = this._scaleMaxWidth * mapResolution * Unit.getInchesPerUnit(currentBaseLayerUnits);

            // decide whether to use large or small scale units. it's independent of the map unit
            var topUnits:String;
            var bottomUnits:String;
            if (maxSizeData > 100000) {
                topUnits = this.topOutUnits;
                bottomUnits = this._bottomOutUnits;
            }
            else {
                topUnits = this.topInUnits;
                bottomUnits = this._bottomInUnits;
            }

            // and to map units units
            var topMax:Number = maxSizeData / Unit.getInchesPerUnit(topUnits);
            var bottomMax:Number = maxSizeData / Unit.getInchesPerUnit(bottomUnits);

            // now trim this down to useful block length

            var topRounded:Number = this.getBarLen(topMax);
            var bottomRounded:Number = this.getBarLen(bottomMax);

            // and back to display units
            topMax = topRounded / Unit.getInchesPerUnit(currentBaseLayerUnits) * Unit.getInchesPerUnit(topUnits);
            bottomMax = bottomRounded / Unit.getInchesPerUnit(currentBaseLayerUnits) * Unit.getInchesPerUnit(bottomUnits);

            // and to pixel units
            _topPx = topMax / mapResolution;
            var bottomPx:Number = bottomMax / mapResolution;

            this.graphics.clear();

            var star_commands:Vector.<int> = new Vector.<int>();
            var star_coord:Vector.<Number> = new Vector.<Number>();

            this.graphics.lineStyle(5, 0xFFFFFF, 1.0, false, "normal", null, null, 3);
            // Draw the ScaleLine
            if (Math.round(bottomPx) > Math.round(topPx)) {
               star_coord.push(10);//横条
               star_coord.push(50);//横条
               star_commands.push(1);  //moveto
               star_coord.push(10+Math.round(bottomPx));//横条
               star_coord.push(50);//横条
               star_commands.push(2);  //lineto
            }
            else {
               star_coord.push(10);//横条
               star_coord.push(50);//横条
               star_commands.push(1);  //moveto
               star_coord.push(10+Math.round(topPx));//横条
               star_coord.push(50);//横条
               star_commands.push(2);  //lineto
            }

            star_coord.push(10+ Math.round(topPx));//upper
            star_coord.push(40);//upper
            star_commands.push(1);  //moveto
            star_coord.push(10+ Math.round(topPx));//upper
            star_coord.push(50);//upper
            star_commands.push(2);  //lineto


            star_coord.push(10+Math.round(bottomPx));//bottom
            star_coord.push(50);//bottom
            star_commands.push(1);  //moveto
            star_coord.push(10+Math.round(bottomPx));//bottom
            star_coord.push(60);//bottom
            star_commands.push(2);  //lineto
            //左侧竖条

            star_coord.push(10);//bottom
            star_coord.push(40);//bottom
            star_commands.push(1);  //moveto
            star_coord.push(10);//bottom
            star_coord.push(60);//bottom
            star_commands.push(2);  //lineto

            this.graphics.drawPath(star_commands, star_coord);


            this.graphics.lineStyle(2, 0x000000, 1.0, false, "normal", null, null, 3);
            this.graphics.drawPath(star_commands, star_coord);

  /*          //先画白底
            this.graphics.lineStyle(1, 0xFFFFFF, 1.0, false, "normal", null, null, 3);
            this.graphics.beginFill(0xFFFFFF);
            // Draw the ScaleLine
            if (Math.round(bottomPx) > Math.round(topPx)) {
                this.graphics.drawRect(8, 48, Math.round(bottomPx) + 4, 4); //横条
                this.graphics.drawRect(8 + Math.round(topPx), 38, 4, 12);
                this.graphics.drawRect(8 + Math.round(bottomPx), 50, 4, 12);
            }
            else {
                this.graphics.drawRect(8, 48, Math.round(topPx) + 4, 4);
                this.graphics.drawRect(8 + Math.round(topPx), 38, 4, 12);
                this.graphics.drawRect(8 + Math.round(bottomPx), 50, 4, 12);
            }
            //左侧竖条
            this.graphics.drawRect(8, 38, 4, 24);
            this.graphics.endFill();

            //再画比例线
            this.graphics.lineStyle(1, this._colorScaleLine, 1.0, false, "normal", null, null, 3);
            this.graphics.beginFill(this._colorScaleLine);
            // Draw the ScaleLine
            if (Math.round(bottomPx) > Math.round(topPx)) {
               this.graphics.drawRect(10, 50, Math.round(bottomPx), 2); //横条
               this.graphics.drawRect(10 + Math.round(topPx), 40, 2, 10);
               this.graphics.drawRect(10 + Math.round(bottomPx), 50, 2, 10);
            }
            else {
               this.graphics.drawRect(10, 50, Math.round(topPx), 2);
               this.graphics.drawRect(10 + Math.round(topPx), 40, 2, 10);
               this.graphics.drawRect(10 + Math.round(bottomPx), 50, 2, 10);
            }
            //左侧竖条
            this.graphics.drawRect(10, 40, 2, 20);
            this.graphics.endFill();*/


            labelMiles = new TextField();
            labelMiles.text = bottomRounded + " " + bottomUnits;
            labelMiles.x = 15;
            labelMiles.y = 50;

            labelKm = new TextField();
            labelKm.text = topRounded + " " + topUnits;
            labelKm.x = 15;
            labelKm.y = 30;

            var labelFormat:TextFormat = new TextFormat();
            labelFormat.size = 11;
            labelFormat.color = this._colorText;
            labelFormat.font = "微软雅黑";

            this.labelKm.defaultTextFormat = labelFormat ;
            this.labelMiles.defaultTextFormat = labelFormat ;
            this.addChild(labelMiles);
            this.addChild(labelKm);

            //Calcul scale
        /* var sizeCM:Number = (topPx)/((this.parentApplication.height)*(this.parentApplication.width))*2.54;
         var scaleD:Number; */

             //Show the scale 1/xxxxx
        /* if(labelScaleKm != null)
           {
           idScaleLine.removeChild(labelScaleKm);
           }
           labelScaleKm = new Label();
           labelScaleKm.text = "1/"+Math.round(scaleD).toString();
           labelScaleKm.x = this.position.x;
           labelScaleKm.y = 0;
         this.idScaleLine.addChild(labelScaleKm);*/
        }

        // GETTERS AND SETTERS
        public function get labelKm():TextField {
            return _labelKm;
        }

        public function set labelKm(value:TextField):void {
            _labelKm = value;
        }

        public function get labelMiles():TextField {
            return _labelMiles;
        }

        public function set labelMiles(value:TextField):void {
            _labelMiles = value;
        }

        public function get topPx():Number {
            return _topPx;
        }

        public function set topPx(value:Number):void {
            _topPx = value;
        }

        public function get scaleMaxWidth():Number {
            return _scaleMaxWidth;
        }

        public function set scaleMaxWidth(value:Number):void {
            _scaleMaxWidth = value;
        }

        public function get topOutUnits():String {
            return _topOutUnits;
        }

        public function set topOutUnits(value:String):void {
            _topOutUnits = value;
        }

        public function get topInUnits():String {
            return _topInUnits;
        }

        public function set topInUnits(value:String):void {
            _topInUnits = value;
        }

        public function get bottomOutUnits():String {
            return _bottomOutUnits;
        }

        public function set bottomOutUnits(value:String):void {
            _bottomOutUnits = value;
        }

        public function get bottomInUnits():String {
            return _bottomInUnits;
        }

        public function set bottomInUnits(value:String):void {
            _bottomInUnits = value;
        }

        /**
         * Color of the text in labels. Default is grey (0x000000)
         */
        public function get colorText():int
        {
           return _colorText;
        }

        /**
         * @private
         */
        public function set colorText(value:int):void
        {
           _colorText = value;
        }

        /**
         * Color of the scale line. Default is grey (0x666666)
         */
        public function get colorScaleLine():int
        {
           return _colorScaleLine;
        }

        /**
         * @private
         */
        public function set colorScaleLine(value:int):void
        {
           _colorScaleLine = value;
        }


    }
}

